#ifndef cexceptions_cexceptions_h
#define cexceptions_cexceptions_h

#include <setjmp.h>
#include <cexceptions/TryCatchContextStack.h>

#define _cexceptions_NOTHING(...) 
#define _cexceptions_ALL(...) __VA_ARGS__
#define __cexceptions_TAIL(ARG0, ...) __VA_ARGS__
#define _cexceptions_TAIL(...) __cexceptions_TAIL(__VA_ARGS__)
#define __cexceptions_NARG0(ARG0, ...) ARG0
#define _cexceptions_NARG0(...) __cexceptions_NARG0(__VA_ARGS__,)
#define _cexceptions_NARG1(...) _cexceptions_NARG0(_cexceptions_TAIL(__VA_ARGS__),)
#define _cexceptions_OPT(...) _cexceptions_NARG1(__VA_OPT__(,) _cexceptions_ALL, _cexceptions_NOTHING)
#define _cexceptions_NOPT(...) _cexceptions_NARG1(__VA_OPT__(,) _cexceptions_NOTHING, _cexceptions_ALL)
#define _cexceptions_IF_EMPTY(VAL, TRUE, FALSE) _cexceptions_NARG1(_cexceptions_OPT(VAL)(,) FALSE, TRUE)
#define _cexceptions_IF_NEMPTY(VAL, TRUE, FALSE) _cexceptions_IF_EMPTY(VAL, FALSE, TRUE)

#define throw(type, message, code, previous, ...)TryCatchContextStack_throw(_cexceptions_NARG1(__VA_OPT__(,) _cexceptions_NARG0(__VA_ARGS__), TryCatchContextStack_default()), type, message, code, previous, __FILE__, __LINE__)
#define thrown(...)TryCatchContextStack_getException(_cexceptions_NARG1(__VA_OPT__(,) _cexceptions_NARG0(__VA_ARGS__), TryCatchContextStack_default()))
#define propagate(...)TryCatchContextStack_propagate(_cexceptions_NARG1(__VA_OPT__(,) _cexceptions_NARG0(__VA_ARGS__), TryCatchContextStack_default()))
#define try(...)switch(setjmp(TryCatchContextStack_push(_cexceptions_NARG1(__VA_OPT__(,) _cexceptions_NARG0(__VA_ARGS__), TryCatchContextStack_default())))){case TRY:{
#define catch(...);TryCatchContextStack_pop(_cexceptions_IF_NEMPTY(_cexceptions_NARG1(__VA_ARGS__), _cexceptions_NARG1(__VA_ARGS__), TryCatchContextStack_default()));break;}_cexceptions_IF_NEMPTY(_cexceptions_NARG0(__VA_ARGS__), case _cexceptions_NARG0(__VA_ARGS__), default):{
#define etry(...);TryCatchContextStack_pop(_cexceptions_NARG1(__VA_OPT__(,) _cexceptions_NARG0(__VA_ARGS__), TryCatchContextStack_default()));break;}}

#endif